package libs

import (
	"bytes"
	"encoding/binary"
	"errors"
	"io"
	"math"
)

func WriteByte(writer io.Writer, target interface{}) {
	e := binary.Write(writer, binary.LittleEndian, target)
	if e != nil {
		panic(e)
	}
}

func ReadByte(reader io.Reader, target interface{}) {
	e := binary.Read(reader, binary.LittleEndian, target)
	if e != nil {
		panic(e)
	}
}

func SetValueAt(buffer []byte, pos int, data interface{}) error {
	buf := new(bytes.Buffer)
	err := binary.Write(buf, binary.BigEndian, data)
	if err != nil {
		return errors.New("binary.Write failed:" + err.Error())
	}
	copy(buffer[pos:], buf.Bytes())
	return nil
}

func GetValueAt(buffer []byte, pos int, value interface{}) error {
	buf := bytes.NewReader(buffer[pos:])
	if err := binary.Read(buf, binary.BigEndian, value); err != nil {
		return errors.New("binary.Read failed:" + err.Error())
	}
	return nil
}

func GetRealAt(buffer []byte, pos int) (float32, error) {
	var value uint32
	err := GetValueAt(buffer, pos, &value)
	if err != nil {
		return 0, err
	}
	float := math.Float32frombits(value)
	return float, nil
}

func SetRealAt(buffer []byte, pos int, value float32) error {
	return SetValueAt(buffer, pos, math.Float32bits(value))
}

func GetLRealAt(buffer []byte, pos int) (float64, error) {
	var value uint64
	err := GetValueAt(buffer, pos, &value)
	if err != nil {
		return 0, err
	}
	float := math.Float64frombits(value)
	return float, nil
}

func SetLRealAt(Buffer []byte, Pos int, Value float64) error {
	return SetValueAt(Buffer, Pos, math.Float64bits(Value))
}

func SetBoolAt(b uint16, bitPos uint, data bool) uint16 {
	if data {
		return b | (1 << bitPos)
	}
	return b &^ (1 << bitPos)
}

func GetBoolAt(b uint16, pos uint) bool {
	return b&(1<<pos) != 0
}
